﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MapCenterSystem.DataInfo;
using System.Drawing;
using MapCenterSystem.DefineType;
using System.IO;
using MapCenterSystem.ServiceProvider.GoogleMap;
using MapCenterSystem.ServiceProvider.LocalMap;
using MapCenterSystem.Utility;
using MapCenterSytem.Process;

namespace MobiMap_Service.Models
{
    public class MapHandler
    {
        #region Cac thuoc tinh
        static int TILE_SIZE = 256;
        static int MAX_WIDTH = TILE_SIZE * 2;
        static int MAX_HEIGHT = TILE_SIZE * 2;
        static int DEFAULT_WIDTH = 512;
        static int DEFAULT_HEIGHT = 512;
        static int DEFAULT_ZOOM = 15;
        static int DEFAULT_TYPE = 0;
        static int MAX_ZOOM = 17;
        static int MIN_ZOOM = 14;
        static double DEFAULT_LONG = 106.682374;
        static double DEFAULT_LAT = 10.762737;

        int screenWidth = DEFAULT_WIDTH;
        int screenHeight = DEFAULT_HEIGHT;

        private string imgFlagRootPath = Helper.ChuanHoaDuongDan("Image");

        // ???
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
        #endregion

        MapInfoEx map = new MapInfoEx();
        public Image GetMapDefault()
        {
            map.MapSource = 0;
            map.Zoom = DEFAULT_ZOOM;
            map.Size = new Size(screenWidth, screenHeight);
            map.MapType = DEFAULT_TYPE;
            map.CoordinateCenter = new Coordinate(DEFAULT_LAT, DEFAULT_LONG);
            map.GlobalToMap();
            map.Tile = new Point(map.MapCenter.X / TILE_SIZE, map.MapCenter.Y / TILE_SIZE);
            map.MapStore = Helper.ChuanHoaDuongDan("MapData");
            Image result;
            if (map.MapSource == 0)
            {
                GoogleMapProviderEx g = new GoogleMapProviderEx();
                // Khi thiếu ảnh, sẽ bị văng khỏi try và vào catch -> Load bản đồ mặc định
                result = g.GetMapImage(map);
            }
            else
            {
                LocalMapProviderEx g = new LocalMapProviderEx();
                result = g.GetMapImage(map);
            }
            return result;
        }

        public Image ChangeImage(double latitude, double longitude)
        {
            map.MapSource = 0;
            map.Zoom = DEFAULT_ZOOM;
            map.Size = new Size(screenWidth, screenHeight);
            map.MapType = DEFAULT_TYPE;
            map.CoordinateCenter = new Coordinate(latitude, longitude);
            map.GlobalToMap();
            map.Tile = new Point(map.MapCenter.X / TILE_SIZE, map.MapCenter.Y / TILE_SIZE);
            map.MapStore = Helper.ChuanHoaDuongDan("MapData");
            Image result;
            if (map.MapSource == 0)
            {
                GoogleMapProviderEx g = new GoogleMapProviderEx();
                // Khi thiếu ảnh, sẽ bị văng khỏi try và vào catch -> Load bản đồ mặc định
                result = g.GetMapImage(map);
            }
            else
            {
                LocalMapProviderEx g = new LocalMapProviderEx();
                result = g.GetMapImage(map);
            }
            return result;
        }

        public bool DrawFlag(Image imageMap, string imgFlagPath, int x, int y)
        {

            Image flag = Image.FromFile(imgFlagPath);
            int left = x - flag.Width / 2;
            int top = y - flag.Height;

            if (left < -flag.Width || left > imageMap.Width || top < -flag.Height || top > imageMap.Height)
                return false;

            Graphics g = Graphics.FromImage(imageMap);
            g.DrawImage(flag, left, top, 30, 50);

            return true;
        }

        public Image DrawFlagInMap(double latitude, double longitude)
        {
            map.CoordinateCenter = new Coordinate(latitude, longitude);
            Image mapImage = ChangeImage(latitude, longitude);
            Point addrPoint = Point.Empty;
            addrPoint = LocateConvert.ToPoint(new Coordinate(latitude, longitude), map.Zoom);
            int flagX = addrPoint.X - (map.MapCenter.X - mapImage.Width / 2);
            int flagY = addrPoint.Y - (map.MapCenter.Y - mapImage.Height / 2);
            bool rsDraw;
            rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerGreen.png", flagX, flagY);
            return mapImage;
        }

        //truyền vào tọa độ 2 điểm đầu cuối
        // dùng 4 tham số đầu vào
        //public Image DrawStreetInMap(double lat1, double long1, double lat2, double long2)
        //{
        //    List<GraphNodeInfoEx> lstGraphNode = new List<GraphNodeInfoEx>();
        //    List<Point> lstPoint = new List<Point>();
        //    GraphNodeInfoEx node = new GraphNodeInfoEx();

        //    node.Location.Latitude = lat1;
        //    node.Location.Longitude = long1;
        //    lstGraphNode.Add(node);
        //    node.Location.Latitude = lat2;
        //    node.Location.Longitude = long2;
        //    lstGraphNode.Add(node);

        //    map.CoordinateCenter = new Coordinate(lat1, long1);
        //    // ve map
        //    Image mapImage = ChangeImage(lat1, long1);
        //    lstPoint = ToListScreenPoint(lstGraphNode, map.MapCenter, mapImage.Width, mapImage.Height, map.Zoom);

        //    //ve duong di 
        //    mapImage = DrawDirection(mapImage, map.MapCenter, lstPoint);

        //    //ve 2 diem dau cuoi
        //    int startX = lstPoint[0].X;
        //    int startY = lstPoint[0].Y;
        //    bool rsDraw;
        //    rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerGreen.png", startX, startY);
        //    int endX = lstPoint[lstPoint.Count - 1].X;
        //    int endY = lstPoint[lstPoint.Count - 1].Y;
        //    rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerRed.png", endX, endY);
        //    return mapImage;
        //}

        // dùng 2tham số đầu vào
        public Image DrawStreetInMap(GraphNodeInfoEx node1, GraphNodeInfoEx node2)
        {
            List<GraphNodeInfoEx> lstGraphNode = new List<GraphNodeInfoEx>();
            List<Point> lstPoint = new List<Point>();

            lstGraphNode.Add(node1);
            lstGraphNode.Add(node2);

            map.CoordinateCenter = new Coordinate(node1.Location.Latitude, node1.Location.Longitude);
            // ve map
            Image mapImage = ChangeImage(node1.Location.Latitude, node1.Location.Longitude);
            lstPoint = ToListScreenPoint(lstGraphNode, map.MapCenter, mapImage.Width, mapImage.Height, map.Zoom);

            //ve duong di 
            mapImage = DrawDirection(mapImage, map.MapCenter, lstPoint);

            //ve 2 diem dau cuoi
            int startX = lstPoint[0].X;
            int startY = lstPoint[0].Y;
            bool rsDraw;
            rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerGreen.png", startX, startY);
            int endX = lstPoint[lstPoint.Count - 1].X;
            int endY = lstPoint[lstPoint.Count - 1].Y;
            rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerRed.png", endX, endY);
            return mapImage;
        }


        // truyền vào tọa độ điểm và list dịch vụ quanh điểm đó
        // dùng 4 tham số đầu vào
        public Image ServiceAround(List<PlaceInfo> lstService, double latitude, double longitude)
        {
            map.CoordinateCenter = new Coordinate(latitude, longitude);
            List<Point> lstServicePoint = new List<Point>();
            Image mapImg = ChangeImage(latitude, longitude);
            lstServicePoint = ToListScreenPoint(lstService, map.MapCenter, mapImg.Width, mapImg.Height, map.Zoom);
            bool rsDraw;
            Point addrPoint = Point.Empty;
            addrPoint = LocateConvert.ToPoint(new Coordinate(latitude, longitude), map.Zoom);
            int flagX = addrPoint.X - (map.MapCenter.X - mapImg.Width / 2);
            int flagY = addrPoint.Y - (map.MapCenter.Y - mapImg.Height / 2);
            rsDraw = DrawFlag(mapImg, imgFlagRootPath + @"\markerRed.png", flagX, flagY);
            for (int i = 0; i < lstServicePoint.Count; i++)
            {
                rsDraw = DrawFlag(mapImg, imgFlagRootPath + @"\markerGreen.png", lstServicePoint[i].X, lstServicePoint[i].Y);
            }
            return mapImg;
        }
        // dùng 2 tham số đầu vào
        public Image ServiceAround(List<PlaceInfo> lstService, Coordinate node)
        {
            map.CoordinateCenter = new Coordinate(node.Latitude, node.Longitude);
            List<Point> lstServicePoint = new List<Point>();
            Image mapImg = ChangeImage(node.Latitude, node.Longitude);
            lstServicePoint = ToListScreenPoint(lstService, map.MapCenter, mapImg.Width, mapImg.Height, map.Zoom);
            bool rsDraw;
            for (int i = 0; i < lstServicePoint.Count; i++)
            {
                rsDraw = DrawFlag(mapImg, imgFlagRootPath + @"\markerGreen.png", lstServicePoint[i].X, lstServicePoint[i].Y);
            }
            return mapImg;
        }

        //Chuyen sang toa do tren man hinh
        public List<Point> ToListScreenPoint(List<GraphNodeInfoEx> lst, Point mapCenter, int scrWidth, int scrHeight, int mapZoom)
        {
            int left = mapCenter.X - scrWidth / 2;
            int top = mapCenter.Y - scrHeight / 2;

            List<Point> lstPoint = new List<Point>();
            Point p;
            for (int i = 0; i < lst.Count; i++)
            {
                p = LocateConvert.ToPoint(lst[i].Location, mapZoom);
                lstPoint.Add(new Point(p.X - left, p.Y - top));
            }
            return lstPoint;
        }

        //Chuyen sang toa do tren man hinh
        public List<Point> ToListScreenPoint(List<PlaceInfo> lst, Point mapCenter, int scrWidth, int scrHeight, int mapZoom)
        {
            int left = mapCenter.X - scrWidth / 2;
            int top = mapCenter.Y - scrHeight / 2;

            List<Point> lstPoint = new List<Point>();
            Point p;
            for (int i = 0; i < lst.Count; i++)
            {
                p = LocateConvert.ToPoint(lst[i].Location, mapZoom);
                lstPoint.Add(new Point(p.X - left, p.Y - top));
            }
            return lstPoint;
        }

        //Ve duong di giua 2 diem tren ban do
        public System.Drawing.Image DrawDirection(System.Drawing.Image image, Point center, List<Point> lstPoint)
        {
            //System.Drawing.Image imgResult = image;

            Graphics g = Graphics.FromImage(image);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            Pen pen = new Pen(Color.Blue, 3);
            Font drawFont = new Font("Arial", 12);
            SolidBrush drawBrush = new SolidBrush(Color.Black);


            Point startNode = lstPoint[0];
            Point endNode = lstPoint[lstPoint.Count - 1];

            for (int i = 0; i < lstPoint.Count - 1; i++)
            {
                g.DrawLine(pen, lstPoint[i], lstPoint[i + 1]);
            }

            return image;
        }

        public Image DrawStreetInMap(Coordinate node1, Coordinate node2)
        {
            List<GraphNodeInfoEx> lstGraphNode = GraphNode.ShortestPath(node1, node2);
            List<Point> lstPoint = new List<Point>();


            map.CoordinateCenter = new Coordinate(node1.Latitude, node1.Longitude);
            // ve map
            Image mapImage = ChangeImage(node1.Latitude, node1.Longitude);
            lstPoint = ToListScreenPoint(lstGraphNode, map.MapCenter, mapImage.Width, mapImage.Height, map.Zoom);

            //ve duong di 
            mapImage = DrawDirection(mapImage, map.MapCenter, lstPoint);

            //ve 2 diem dau cuoi
            int startX = lstPoint[0].X;
            int startY = lstPoint[0].Y;
            bool rsDraw;
            rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerGreen.png", startX, startY);
            int endX = lstPoint[lstPoint.Count - 1].X;
            int endY = lstPoint[lstPoint.Count - 1].Y;
            rsDraw = DrawFlag(mapImage, imgFlagRootPath + @"\markerRed.png", endX, endY);
            return mapImage;
        }
    }
}